import numpy as np


def point_to_line_projection(point, line_start, line_end):
    """
    计算点到直线的投影点
    
    参数:
        point: 待投影的点，形状为(2,)的NumPy数组或列表 [x, y]
        line_start: 直线起点，形状为(2,)的NumPy数组或列表 [x1, y1]
        line_end: 直线终点，形状为(2,)的NumPy数组或列表 [x2, y2]
    
    返回:
        投影点坐标 [x, y]
    """
    # 转换为NumPy数组
    point = np.array(point)
    line_start = np.array(line_start)
    line_end = np.array(line_end)
    
    # 计算向量AB和AP
    AB = line_end - line_start
    AP = point - line_start
    
    # 计算投影比例t
    t = np.dot(AP, AB) / np.dot(AB, AB)
    
    print(f'投影比例{t}')
    # 计算投影点
    projection = line_start + t * AB
    
    return projection
# 定义直线和点
line_start = np.array([1, 1])
line_end = np.array([20, 45])
point = np.array([5, 40])

# 计算投影点
projection = point_to_line_projection(point, line_start, line_end)
print("投影点坐标:", projection)

# 可视化
import matplotlib.pyplot as plt
# 设置中文字体支持（可选）
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.figure(figsize=(8, 6))
plt.plot([line_start[0], line_end[0]], [line_start[1], line_end[1]], 'b-', label='直线AB')
plt.plot(point[0], point[1], 'ro', label='点P')
plt.plot(projection[0], projection[1], 'go', label='投影点Q')

# 绘制垂线
plt.plot([point[0], projection[0]], [point[1], projection[1]], 'k--', label='垂线')

plt.legend()
plt.grid(True)
plt.axis('equal')
plt.title('点到直线的投影')
plt.show()